﻿using System;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Linq;
using DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Packaging;
using HtmlAgilityPack;
using OpenXmlPowerTools;
using XBLMS.Core.Utils.Office.Word2Html;
using XBLMS.Enums;
using XBLMS.Models;
using XBLMS.Services;
using XBLMS.Utils;

namespace XBLMS.Core.Utils.Office
{
    public class WordManager
    {
        private string ImageDirectoryPath { get; set; }
        private string ImageDirectoryUrl { get; set; }
        private bool IsFirstLineTitle { get; set; }
        private bool IsClearFormat { get; set; }
        private bool IsFirstLineIndent { get; set; }
        private bool IsClearFontSize { get; set; }
        private bool IsClearFontFamily { get; set; }
        private bool IsClearImages { get; set; }
        private string DocsFilePath { get; set; }
        private string DocsFileTitle { get; set; }

        public string Title { get; set; }
        public string ImageUrl { get; set; }
        public string Body { get; set; }

        public WordManager(bool isFirstLineTitle, bool isClearFormat, bool isFirstLineIndent, bool isClearFontSize, bool isClearFontFamily, bool isClearImages, string docsFilePath, string docsFileTitle)
        {
            IsFirstLineTitle = isFirstLineTitle;
            IsClearFormat = isClearFormat;
            IsFirstLineIndent = isFirstLineIndent;
            IsClearFontSize = isClearFontSize;
            IsClearFontFamily = isClearFontFamily;
            IsClearImages = isClearImages;
            DocsFilePath = docsFilePath;
            DocsFileTitle = docsFileTitle;
        }

        public void  InitAsync(IPathManager pathManager)
        {
            var fileName = PathUtils.GetFileName(DocsFilePath);
            ImageDirectoryPath = PathUtils.Combine(pathManager.WebRootPath, PathUtils.GetMaterialVirtualDirectoryPath(UploadType.Image));
            ImageDirectoryUrl = PathUtils.GetMaterialVirtualFilePath(UploadType.Image, fileName);
        }

        public async Task ParseAsync(IPathManager pathManager)
        {
            InitAsync(pathManager);

            try
            {
                ConvertToHtml();
                if (string.IsNullOrEmpty(Body))
                {
                    await ConvertToHtmlAsync();
                }
            }
            catch
            {
                await ConvertToHtmlAsync();
            }

            XBLMS.Utils.FileUtils.DeleteFileIfExists(DocsFilePath);

            if (string.IsNullOrEmpty(Title))
            {
                Title = DocsFileTitle;
            }

            if (IsFirstLineTitle)
            {
                var contentTitle = RegexUtils.GetInnerContent("p", Body);
                contentTitle = StringUtils.StripTags(contentTitle);
                if (!string.IsNullOrEmpty(contentTitle))
                {
                    contentTitle = contentTitle.Trim();
                    contentTitle = contentTitle.Trim('　', ' ');
                    contentTitle = StringUtils.StripEntities(contentTitle);
                }

                if (!string.IsNullOrEmpty(contentTitle))
                {
                    Title = contentTitle;
                }
            }

            if (IsClearFormat)
            {
                Body = HtmlUtils.ClearFormat(Body);
            }

            if (IsFirstLineIndent)
            {
                Body = HtmlUtils.FirstLineIndent(Body);
            }

            if (IsClearFontSize)
            {
                Body = HtmlUtils.ClearFontSize(Body);
            }

            if (IsClearFontFamily)
            {
                Body = HtmlUtils.ClearFontFamily(Body);
            }
        }

        public async Task ConvertToHtmlAsync()
        {
            FileStream stream = new FileStream(DocsFilePath, FileMode.Open, FileAccess.Read);
            var npoiDoc = new NpoiDoc();
            Body = await npoiDoc.NpoiDocx(stream, UploadImageUrlDelegate);
        }

        private string UploadImageUrlDelegate(byte[] imgByte, string picType)
        {
            var extension = StringUtils.ToLower(picType.Split('/')[1]);
            var imageFileName = StringUtils.GetShortGuid(false) + "." + extension;

            var imageFilePath = PathUtils.Combine(ImageDirectoryPath, imageFileName);
            try
            {
                ImageUtils.Save(imgByte, imageFilePath);

                ImageUtils.ResizeImageIfExceeding(imageFilePath,100);


                var imgSrc = PageUtils.Combine(ImageDirectoryUrl, imageFileName);

                if (string.IsNullOrEmpty(ImageUrl))
                {
                    ImageUrl = imgSrc;
                }

                return imgSrc;
            }
            catch
            {

            }

            return $"data:{picType};base64,{Convert.ToBase64String(imgByte)}";
        }

        private void ConvertToHtml()
        {
            //var fi = new FileInfo(DocsFilePath);

            //var byteArray = File.ReadAllBytes(fi.FullName);
            //using (var memoryStream = new MemoryStream())
            //{
            //    memoryStream.Write(byteArray, 0, byteArray.Length);

            //    using (var wDoc = WordprocessingDocument.Open(memoryStream, true))
            //    {
            //        var part = wDoc.CoreFilePropertiesPart;
            //        if (part != null)
            //        {
            //            Title = (string)part.GetXDocument().Descendants(DC.title).FirstOrDefault();
            //        }

            //        var htmlSettings = new HtmlConverterSettings
            //        {
            //            // AdditionalCss = "body { margin: 1cm auto; max-width: 20cm; padding: 0; }",
            //            PageTitle = Title,
            //            FabricateCssClasses = true,
            //            CssClassPrefix = "pt-",
            //            RestrictToSupportedLanguages = false,
            //            RestrictToSupportedNumberingFormats = false,
            //            ImageHandler = imageInfo =>
            //            {
            //                if (IsClearImages || string.IsNullOrEmpty(ImageDirectoryPath)) return null;
            //                DirectoryUtils.CreateDirectoryIfNotExists(ImageDirectoryPath);

            //                var extension = StringUtils.ToLower(imageInfo.ContentType.Split('/')[1]);
            //                ImageFormat imageFormat = null;
            //                if (extension == "png")
            //                    imageFormat = ImageFormat.Png;
            //                else if (extension == "gif")
            //                    imageFormat = ImageFormat.Gif;
            //                else if (extension == "bmp")
            //                    imageFormat = ImageFormat.Bmp;
            //                else if (extension == "jpeg")
            //                    imageFormat = ImageFormat.Jpeg;
            //                else if (extension == "tiff")
            //                {
            //                    // Convert tiff to gif.
            //                    extension = "gif";
            //                    imageFormat = ImageFormat.Gif;
            //                }
            //                else if (extension == "x-wmf")
            //                {
            //                    extension = "wmf";
            //                    imageFormat = ImageFormat.Wmf;
            //                }

            //                // If the image format isn't one that we expect, ignore it,
            //                // and don't return markup for the link.
            //                if (imageFormat == null)
            //                    return null;

            //                var imageFileName = StringUtils.GetShortGuid(false) + "." + extension;

            //                var imageFilePath = PathUtils.Combine(ImageDirectoryPath, imageFileName);
            //                try
            //                {
            //                    imageInfo.Bitmap.Save(imageFilePath, imageFormat);

            //                    if (Site.IsImageAutoResize)
            //                    {
            //                        ImageUtils.ResizeImageIfExceeding(imageFilePath, Site.ImageAutoResizeWidth);
            //                    }

            //                    // AddWaterMarkAsync(Site, filePath);
            //                }
            //                catch (System.Runtime.InteropServices.ExternalException)
            //                {
            //                    return null;
            //                }
            //                var imageSource = PageUtils.Combine(ImageDirectoryUrl, imageFileName);
            //                if (string.IsNullOrEmpty(ImageUrl))
            //                {
            //                    ImageUrl = imageSource;
            //                }

            //                var img = new XElement(
            //                  Xhtml.img,
            //                  new XAttribute(NoNamespace.src, imageSource),
            //                  // imageInfo.ImgStyleAttribute,
            //                  imageInfo.AltText != null ? new XAttribute(NoNamespace.alt, imageInfo.AltText) : null
            //                );
            //                return img;
            //            }
            //        };
            //        var htmlElement = HtmlConverter.ConvertToHtml(wDoc, htmlSettings);

            //        // Produce HTML document with <!DOCTYPE html > declaration to tell the browser
            //        // we are using HTML5.
            //        var html = new XDocument(
            //            new XDocumentType("html", null, null, null),
            //            htmlElement);

            //        // Note: the xhtml returned by ConvertToHtmlTransform contains objects of type
            //        // XEntity.  PtOpenXmlUtil.cs define the XEntity class.  See
            //        // http://blogs.msdn.com/ericwhite/archive/2010/01/21/writing-entity-references-using-linq-to-xml.aspx
            //        // for detailed explanation.
            //        //
            //        // If you further transform the XML tree returned by ConvertToHtmlTransform, you
            //        // must do it correctly, or entities will not be serialized properly.

            //        var htmlString = html.ToString(SaveOptions.DisableFormatting);
            //        var htmlDoc = new HtmlDocument();
            //        htmlDoc.LoadHtml(htmlString);
            //        var style = IsClearFormat ? string.Empty : htmlDoc.DocumentNode.SelectSingleNode("//style").OuterHtml;
            //        var body = htmlDoc.DocumentNode.SelectSingleNode("//body").InnerHtml;

            //        Body = $"{style}{Environment.NewLine}{body}";
            //    }
            //}
        }

        public static void OpenAndAddTextToWordDocument(string filepath, string txt)
        {
            // Open a WordprocessingDocument for editing using the filepath.
            var wordprocessingDocument = WordprocessingDocument.Open(filepath, true);

            // Assign a reference to the existing document body.
            var body = wordprocessingDocument.MainDocumentPart.Document.Body;
            
            // Add new text.
            var para = body.AppendChild(new Paragraph());
            var run = para.AppendChild(new Run());
            run.AppendChild(new Text(txt));
            
            // Close the handle explicitly.
            wordprocessingDocument.Close();
        }
    }
}
